package ext.tianma.bom.util;

import java.rmi.RemoteException;
import java.sql.Timestamp;

import org.apache.commons.lang.exception.ExceptionUtils;

import wt.access.NotAuthorizedException;
import wt.change2.VersionableChangeItem;
import wt.enterprise.RevisionControlled;
import wt.epm.util.EPMSoftTypeServerUtilities;
import wt.fc.ObjectIdentifier;
import wt.fc.ObjectReference;
import wt.fc.PersistInfo;
import wt.fc.Persistable;
import wt.fc.PersistenceHelper;
import wt.fc.QueryResult;
import wt.iba.definition.IBADefinitionException;
import wt.iba.definition.StringDefinition;
import wt.iba.definition.TimestampDefinition;
import wt.iba.definition.litedefinition.AttributeDefDefaultView;
import wt.iba.definition.litedefinition.StringDefView;
import wt.iba.definition.litedefinition.TimestampDefView;
import wt.iba.definition.service.IBADefinitionHelper;
import wt.iba.value.FloatValue;
import wt.iba.value.StringValue;
import wt.iba.value.TimestampValue;
import wt.method.RemoteAccess;
import wt.method.RemoteMethodServer;
import wt.query.ClassAttribute;
import wt.query.QueryException;
import wt.query.QuerySpec;
import wt.query.SearchCondition;
import wt.query.SubSelectExpression;
import wt.type.TypeDefinitionReference;
import wt.type.Typed;
import wt.type.TypedUtilityServiceHelper;
import wt.util.WTException;
import wt.vc.VersionControlHelper;

import com.ptc.core.logging.Log;
import com.ptc.core.logging.LogFactory;
import com.ptc.core.meta.common.impl.WCTypeIdentifier;
import com.ptc.core.meta.type.mgmt.common.TypeDefinitionDefaultView;
import com.ptc.core.meta.type.mgmt.server.impl.WTTypeDefinition;

public class QueryUtil implements RemoteAccess {

	private static Log logger = LogFactory.getLog(QueryUtil.class);

	private static final String CLOSE_PAREN = String.valueOf(')');

	public static void appendTypeCondition(QuerySpec querySpec, String typeName) throws RemoteException, WTException {
		TypeDefinitionReference softTypeDefRef = TypedUtilityServiceHelper.service.getTypeDefinitionReference(typeName);
		TypeDefinitionDefaultView s = EPMSoftTypeServerUtilities.getTypeDefinition(softTypeDefRef);
		WCTypeIdentifier i = (WCTypeIdentifier) EPMSoftTypeServerUtilities.getTypeIdentifier(softTypeDefRef);
		WTTypeDefinition def = (WTTypeDefinition) PersistenceHelper.manager.refresh(s.getObjectID());
		SearchCondition typeCondition = new SearchCondition(querySpec.getPrimaryClass(),
				Typed.TYPE_DEFINITION_REFERENCE + ".key.branchId", SearchCondition.EQUAL,
				softTypeDefRef.getKey().getBranchId());
		if (querySpec.getConditionCount() > 0 && querySpec.getWhere().endsWith(CLOSE_PAREN))
			querySpec.appendAnd();
		querySpec.appendWhere(typeCondition);
	}

	/**
	 * @param querySpec
	 * @return
	 * @throws QueryException
	 * @throws WTException
	 */
	/*
	 * public static int appendIBAAttributeJoin(QuerySpec querySpec, String
	 * attributeName) throws QueryException, WTException { int i =
	 * querySpec.appendClassList(StringValue.class, false); StringDefinition ibaDef
	 * = getStringDefByPath(attributeName); if(querySpec.getConditionCount() > 0 &&
	 * querySpec.getWhere().endsWith(CLOSE_PAREN)) querySpec.appendAnd();
	 * SearchCondition searchcondition0 = new
	 * SearchCondition(querySpec.getPrimaryClass(),
	 * "thePersistInfo.theObjectIdentifier.id", StringValue.class,
	 * StringValue.IBAHOLDER_REFERENCE + ".key.id");
	 * querySpec.appendWhere(searchcondition0, new int[] { 0, i });
	 * querySpec.appendAnd(); querySpec.appendWhere(new
	 * SearchCondition(StringValue.class, "definitionReference.key.id",
	 * SearchCondition.EQUAL,
	 * PersistenceHelper.getObjectIdentifier(ibaDef).getId()), new int[] { i });
	 * return i; }
	 */

	/**
	 * @param querySpec
	 * @param selectIndex
	 * @param value
	 * @throws QueryException
	 */
	public static void appendIBAAttributeValueCondition(QuerySpec querySpec, int selectIndex, String operation,
			String value) throws QueryException {
		querySpec.appendAnd();
		SearchCondition searchCondition = new SearchCondition(StringValue.class, StringValue.VALUE2, operation, value);
		querySpec.appendWhere(searchCondition, new int[] { selectIndex });
	}

	/**
	 * @param querySpec
	 * @param selectIndex
	 * @param value
	 * @throws QueryException
	 */
	public static void appendIBAAttributeValueConditionUpper(QuerySpec querySpec, int selectIndex, String operation,
			String value) throws QueryException {
		querySpec.appendAnd();
		SearchCondition searchCondition = new SearchCondition(StringValue.class, StringValue.VALUE, operation, value);
		querySpec.appendWhere(searchCondition, new int[] { selectIndex });
	}

	/**
	 * @param querySpec
	 * @param attributeName
	 * @param operation
	 * @param value
	 * @throws QueryException
	 * @throws WTException
	 */
	/*
	 * public static void appendIBASearchCondition(QuerySpec querySpec, String
	 * attributeName, String operation,String value) throws QueryException,
	 * WTException { int index = appendIBAAttributeJoin(querySpec, attributeName);
	 * appendIBAAttributeValueCondition(querySpec, index, operation, value); }
	 */

	/**
	 * @param querySpec
	 * @param attributeName
	 * @param operation
	 * @param value
	 * @throws QueryException
	 * @throws WTException
	 */
	/*
	 * public static void appendIBASearchConditionUpper(QuerySpec querySpec, String
	 * attributeName, String operation,String value) throws QueryException,
	 * WTException { int index = appendIBAAttributeJoin(querySpec, attributeName);
	 * appendIBAAttributeValueConditionUpper(querySpec, index, operation, value); }
	 */

	/**
	 * @param ibaKey
	 * @return
	 */
	/*
	 * private static StringDefinition getStringDefByPath(String ibaKey) { if
	 * (!RemoteMethodServer.ServerFlag) { try { return (StringDefinition)
	 * RemoteMethodServer.getDefault().invoke("getStringDefByPath",
	 * EPMUtil.class.getName(), null, new Class[] { String.class }, new Object[] {
	 * ibaKey }); } catch (Exception e) {
	 * logger.error(ExceptionUtils.getStackTrace(e)); } } StringDefinition stringDef
	 * = null; try { AttributeDefDefaultView defView =
	 * IBADefinitionHelper.service.getAttributeDefDefaultViewByPath(ibaKey); if
	 * (defView instanceof StringDefView) { stringDef = (StringDefinition)
	 * ObjectReference.newObjectReference( ((StringDefView)
	 * defView).getObjectID()).getObject(); } } catch (Exception e) {
	 * logger.error("Get IBA Definition [" + ibaKey + "] Error: " +
	 * ExceptionUtils.getStackTrace(e)); } return stringDef; }
	 */

	public static RevisionControlled getLatest(RevisionControlled revisionControlled) {
		RevisionControlled latest = null;
		try {
			QuerySpec queryspec = new QuerySpec(revisionControlled.getClass());
			queryspec.appendWhere(VersionControlHelper.getSearchCondition(revisionControlled.getClass(),
					revisionControlled.getMaster()));
			queryspec.appendAnd();
			queryspec.appendWhere(new SearchCondition(revisionControlled.getClass(), "iterationInfo.latest", "TRUE"),
					new int[] { 0 });
			QueryResult queryresult = PersistenceHelper.manager.find(queryspec);
			if (queryresult.hasMoreElements())
				latest = (RevisionControlled) queryresult.nextElement();
		} catch (WTException e) {
			logger.error(e);
		}
		return latest;

	}

	public static VersionableChangeItem getLatest(VersionableChangeItem versionableChangeItem) {
		VersionableChangeItem latest = null;
		try {
			QuerySpec queryspec = new QuerySpec(versionableChangeItem.getClass());
			queryspec.appendWhere(VersionControlHelper.getSearchCondition(versionableChangeItem.getClass(),
					versionableChangeItem.getMaster()));
			queryspec.appendAnd();
			queryspec.appendWhere(new SearchCondition(versionableChangeItem.getClass(), "latest", "TRUE"),
					new int[] { 0 });
			QueryResult queryresult = PersistenceHelper.manager.find(queryspec);
			if (queryresult.hasMoreElements())
				latest = (VersionableChangeItem) queryresult.nextElement();
		} catch (WTException e) {
			logger.error(e);
		}
		return latest;

	}

	public static void appendIBASearchCondition(QuerySpec querySpec, String attributeName, String operation,
			Timestamp value) throws QueryException, WTException {
		int index = appendIBATimeStampAttributeJoin(querySpec, attributeName);
		appendTimeStampIBAAttributeValueCondition(querySpec, index, operation, value);
	}

	public static int appendIBATimeStampAttributeJoin(QuerySpec querySpec, String attributeName)
			throws QueryException, WTException {
		int i = querySpec.appendClassList(TimestampValue.class, false);
		TimestampDefinition ibaDef = getTimeDefByPath(attributeName);
		if (querySpec.getConditionCount() > 0 && querySpec.getWhere().endsWith(CLOSE_PAREN))
			querySpec.appendAnd();
		SearchCondition searchcondition0 = new SearchCondition(querySpec.getPrimaryClass(),
				"thePersistInfo.theObjectIdentifier.id", TimestampValue.class,
				TimestampValue.IBAHOLDER_REFERENCE + ".key.id");
		querySpec.appendWhere(searchcondition0, new int[] { 0, i });
		querySpec.appendAnd();
		querySpec.appendWhere(new SearchCondition(TimestampValue.class, "definitionReference.key.id",
				SearchCondition.EQUAL, PersistenceHelper.getObjectIdentifier(ibaDef).getId()), new int[] { i });
		return i;
	}

	public static void appendTimeStampIBAAttributeValueCondition(QuerySpec querySpec, int selectIndex, String operation,
			Timestamp value) throws QueryException {
		querySpec.appendAnd();
		SearchCondition searchCondition = new SearchCondition(TimestampValue.class, TimestampValue.VALUE, operation,
				value);
		querySpec.appendWhere(searchCondition, new int[] { selectIndex });
	}

	private static TimestampDefinition getTimeDefByPath(String ibaKey) {
		if (!RemoteMethodServer.ServerFlag) {
			try {
				return (TimestampDefinition) RemoteMethodServer.getDefault().invoke("getTimeDefByPath",
						QueryUtil.class.getName(), null, new Class[] { String.class }, new Object[] { ibaKey });
			} catch (Exception e) {
				logger.error(ExceptionUtils.getStackTrace(e));
			}
		}
		TimestampDefinition timeDef = null;
		try {
			AttributeDefDefaultView defView = IBADefinitionHelper.service.getAttributeDefDefaultViewByPath(ibaKey);
			logger.debug("DEFView=" + defView);
			if (defView instanceof TimestampDefView) {
				timeDef = (TimestampDefinition) ObjectReference
						.newObjectReference(((TimestampDefView) defView).getObjectID()).getObject();
			}
		} catch (Exception e) {
			logger.error("Get IBA Definition [" + ibaKey + "] Error: " + ExceptionUtils.getStackTrace(e));
		}
		return timeDef;
	}

	/**
	 * 拼接对象字符串IBA查询语句
	 */
	public static SearchCondition getIBASearchCondition(Class<?> cls, String ibaName, String ibaValue, String condition)
			throws WTException {
		SubSelectExpression subselect = getStringIBAQuery(ibaName, ibaValue, condition);
		SearchCondition sc = new SearchCondition(
				new ClassAttribute(cls,
						Persistable.PERSIST_INFO + "." + PersistInfo.OBJECT_IDENTIFIER + "." + ObjectIdentifier.ID),
				SearchCondition.IN, subselect);
		return sc;
	}

	/**
	 * 拼接对象字符串IBA查询语句
	 */
	public static SearchCondition getIBASearchConditionByFloat(Class<?> cls, String ibaName, String ibaValue,
			String condition) throws WTException {
		logger.info("=================getIBASearchConditionByFloat start==========");
		SubSelectExpression subselect = getFloatIBAQuery(ibaName, ibaValue, condition);
		SearchCondition sc = new SearchCondition(
				new ClassAttribute(cls,
						Persistable.PERSIST_INFO + "." + PersistInfo.OBJECT_IDENTIFIER + "." + ObjectIdentifier.ID),
				SearchCondition.IN, subselect);
		logger.info("=================getIBASearchConditionByFloat end==========");
		return sc;
	}

	/**
	 * String IBA属性查询
	 */
	private static SubSelectExpression getStringIBAQuery(String ibaName, String ibaValue, String condition)
			throws WTException {

		AttributeDefDefaultView addv = null;
		try {
			addv = IBADefinitionHelper.service.getAttributeDefDefaultViewByPath(ibaName);
		} catch (RemoteException e) {
			e.printStackTrace();
		}
		if (addv == null) {
			throw new IBADefinitionException("系统未定义IBA: " + ibaName);
		}
		long ibaDefId = addv.getObjectID().getId();
		QuerySpec qs = new QuerySpec();
		qs.setAdvancedQueryEnabled(true);
		int idx = qs.appendClassList(StringValue.class, false);
		qs.appendSelect(new ClassAttribute(StringValue.class, "theIBAHolderReference.key.id"), new int[] { idx },
				false);
		qs.appendWhere(
				new SearchCondition(StringValue.class, "definitionReference.key.id", SearchCondition.EQUAL, ibaDefId),
				new int[] { idx });
		qs.appendAnd();
		/*
		 * if(condition.equals(SearchCondition.NOT_NULL)){
		 * logger.info("==============condition start====="+condition);
		 * qs.appendWhere(new SearchCondition(StringValue.class, StringValue.VALUE2,
		 * condition), new int[]{idx});
		 * logger.info("==============condition end====="+condition); }else{
		 */
		System.out.println("=============ibaValue=====>>" + ibaValue);
		System.out.println("=============ibaName=====>>" + ibaName);
		System.out.println("=============condition=====>>" + condition);
		qs.appendWhere(new SearchCondition(StringValue.class, StringValue.VALUE2, SearchCondition.LIKE, ibaValue),
				new int[] { idx });
		// }
		System.out.println("qs======>>>" + qs);
		return new SubSelectExpression(qs);
	}

	/**
	 * String IBA属性查询
	 */
	private static SubSelectExpression getFloatIBAQuery(String ibaName, String ibaValue, String condition) {
		logger.info("=================getFloatIBAQuery start==========");
		SubSelectExpression subexpress = null;
		AttributeDefDefaultView addv = null;
		try {
			try {
				addv = IBADefinitionHelper.service.getAttributeDefDefaultViewByPath(ibaName);
			} catch (IBADefinitionException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (NotAuthorizedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (WTException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		} catch (RemoteException e) {
			e.printStackTrace();
		}
		logger.info("=================getFloatIBAQuery addv==========" + addv);
		if (addv == null) {
			logger.info("=================getFloatIBAQuery 系统未定义IBA: ==========" + ibaName);
			try {
				throw new IBADefinitionException("系统未定义IBA: " + ibaName);
			} catch (IBADefinitionException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		long ibaDefId = addv.getObjectID().getId();
		logger.info("=================getFloatIBAQuery 1111111: ==========" + ibaName);
		QuerySpec qs;
		try {
			qs = new QuerySpec();
			qs.setAdvancedQueryEnabled(true);
			int idx = qs.appendClassList(FloatValue.class, false);
			qs.appendSelect(new ClassAttribute(FloatValue.class, "theIBAHolderReference.key.id"), new int[] { idx },
					false);
			qs.appendWhere(new SearchCondition(FloatValue.class, "definitionReference.key.id", SearchCondition.EQUAL,
					ibaDefId), new int[] { idx });
			qs.appendAnd();
			qs.appendWhere(
					new SearchCondition(FloatValue.class, FloatValue.VALUE, condition, Double.parseDouble(ibaValue)),
					new int[] { idx });
			// }
			subexpress = new SubSelectExpression(qs);
		} catch (QueryException e) {
			logger.info("=================getFloatIBAQuery QueryException: ==========" + e);
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		/*
		 * if(condition.equals(SearchCondition.NOT_NULL)){
		 * logger.info("==============condition start====="+condition);
		 * qs.appendWhere(new SearchCondition(StringValue.class, StringValue.VALUE2,
		 * condition), new int[]{idx});
		 * logger.info("==============condition end====="+condition); }else{
		 */
		return subexpress;
	}
}
